/**
 * Copyright (c) 2020 - present, Inspur Genersoft Co., Ltd.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
import { computed, defineComponent, ref, SetupContext, TransitionGroup, withModifiers } from 'vue';
import { ListViewProps, listViewProps } from './list-view.props';
import { useItem } from './composition/use-item';
import { useSelection } from './composition/use-selection';
import { useSearch } from './composition/use-search';
import getSingleItem from './components/item/single-item.component';
import getContentItem from './components/item/content-item.component';
import getDraggableItem from './components/item/draggable-item.component';
import getContentHeader from './components/header/content-header.component';
import getSearchHeader from './components/header/search-header.component';
import './list-view.scss';
import { useDataView } from './composition/use-data-view';
import { useDraggable } from './composition/use-draggable';
import { useRemove } from './composition/use-remove';
import { useHover } from './composition/use-hover';

export default defineComponent({
    name: 'FListView',
    props: listViewProps,
    emits: ['checkValuesChange', 'clickItem', 'selectionChange', 'removeItem', 'change'] as (string[] & ThisType<void>) | undefined,
    setup(props: ListViewProps, context: SetupContext) {
        const listViewContentRef = ref<any>();
        const listViewType = ref(props.view);
        const listViewHeaderType = ref(props.header);
        const enableMultiSelect = ref(props.multiSelect);
        const cardView = ref(props.view === 'CardView');
        const enablePagination = ref(true);
        const clickItem = ref<any>({});
        const emptyMessage = ref('暂无数据');
        const keepSelect = ref(true);
        const enableMorePageSelect = ref(false);
        const selectDataListWithOtherPager: any[] = [];
        const listidName = ref('id');

        const dataViewComposition = useDataView(props, context);

        const { dataView } = dataViewComposition;

        const listViewClass = computed(() => {
            const classObject = {
                'f-list-view': true,
                'f-list-view-multiple': enableMultiSelect.value
            } as Record<string, boolean>;
            if (props.size !== 'default') {
                classObject[`${props.size}-item`] = true;
            }
            return classObject;
        });

        const listViewGroupClass = computed(() => {
            const classObject = {
                'f-list-view-group': true,
                'd-flex': cardView.value,
                'flex-wrap': cardView.value
            } as Record<string, boolean>;
            return classObject;
        });

        const shouldShowListViewGroupItem = computed(() => !!dataView.value && dataView.value.length > 0);

        const useHoverComposition = useHover();

        const useSelectionComposition = useSelection(props, context, dataViewComposition);

        const useDraggableComposition = useDraggable(props, context, dataViewComposition, useHoverComposition);

        const useRemoveComposition = useRemove(props, context, dataViewComposition);

        const useItemCompostion = useItem(props, context, useDraggableComposition, useHoverComposition, useSelectionComposition);

        const useSearchComposition = useSearch(props, listViewContentRef);

        const showEmpty = computed(() => dataView.value.length === 0);

        const shouldShowEmptyTemplate = computed(() => {
            return showEmpty.value && !context.slots.empty;
        });

        const shouldShowFooter = computed(() => {
            return !!context.slots.footer || enablePagination.value;
        });

        function getRenderFactory() {
            if (listViewType.value === 'SingleView') {
                return getSingleItem;
            }
            if (listViewType.value === 'DraggableView') {
                return getDraggableItem;
            }
            if (listViewType.value === 'ContentView' && context.slots.content) {
                return getContentItem;
            }
            return getSingleItem;
        }

        const renderFactory = getRenderFactory();

        const { renderItem } = renderFactory(props, context, dataViewComposition, useDraggableComposition, useHoverComposition,
            useItemCompostion, useSelectionComposition, useRemoveComposition);

        function getHeaderFactory() {
            if (listViewHeaderType.value === 'SearchBar') {
                return getSearchHeader;
            }
            if (listViewHeaderType.value === 'ContentHeader') {
                return getContentHeader;
            }
            return getSearchHeader;
        }

        const headerFactroy = getHeaderFactory();

        const { renderHeader } = headerFactroy(props, context, useSearchComposition);

        function search(searchingText: string) {
            useSearchComposition.search(searchingText);
        }

        context.expose({ search });

        function onClick(payload: MouseEvent) {
            if (enableMultiSelect.value) {
                payload.preventDefault();
                payload.stopPropagation();
            }
        }

        return () => {
            return (
                <div class={listViewClass.value} onClick={onClick}>
                    {renderHeader()}
                    <div ref={listViewContentRef} class="f-list-view-content">
                        <ul class={listViewGroupClass.value} style="list-style: none;">
                            {shouldShowListViewGroupItem.value &&
                                dataView.value.map((item, index) => renderItem(item, index, clickItem))}
                            {shouldShowEmptyTemplate.value && (
                                <div class="f-list-view-emptydata">
                                    <p class="f-empty-title">{emptyMessage.value}</p>
                                </div>
                            )}
                            {context.slots.empty && context.slots.empty()}
                        </ul>
                    </div>
                    {shouldShowFooter.value && <div class="f-list-view-footer">{context.slots.footer && context.slots.footer()}</div>}
                </div>
            );
        };
    }
});
